﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using BreukTrainer.Model;

namespace BreukTrainer
{
    public partial class Oefenen : Form
    {
        private DataTable breukenLijst;
        private DataTable dtOpgaven;
        private DataTable dtSorterenBreuken;
        private ProgrammeerbareBreukContainer breukContainer;
        private int totaalbewerkingen;
        private int aantalbewerkingen;
        private List<Breuk> sorterenBreuken;
        private List<Breuk> correctGesorteerdeBreuken;
        private Random random;


        public Oefenen()//ok
        {
            InitializeComponent();
            breukenLijst = new DataTable();
            breukenLijst.Columns.Add("#");
            breukenLijst.Columns.Add("Breuk");
            breukenDataGridView.DataSource = breukenLijst;
            breukenDataGridView.Columns[0].Width = 20;
            breukenDataGridView.Columns[0].ReadOnly = true;
            breukenDataGridView.Columns[1].Width = 130;

            //breukContainer = new BreukContainer();
            breukContainer = new ProgrammeerbareBreukContainer();
            aantalBreukenUpDown.Value = 4; //meteen 3 breuken klaarmaken
            sorterenBreuken = new List<Breuk>();
            correctGesorteerdeBreuken = new List<Breuk>();

            dtOpgaven = new DataTable();
            dtOpgaven.Columns.Add("Opgave");
            dtOpgaven.Columns.Add("Antwoord");
            dtOpgaven.Columns.Add("Correct");
            dgvOpgaven.DataSource = dtOpgaven;
            dgvOpgaven.Columns[0].Width = 250;
            dgvOpgaven.Columns[0].ReadOnly = true;
            dgvOpgaven.Columns[1].Width = 60;
            dgvOpgaven.Columns[2].Width = 60;
            dgvOpgaven.Columns[2].ReadOnly = true;
            dgvOpgaven.Columns[2].Visible = false;

            dtSorterenBreuken = new DataTable();
            dtSorterenBreuken.Columns.Add("Breuk");
            dvgSorterenBreuken.DataSource = dtSorterenBreuken;
            dvgSorterenBreuken.Columns[0].Width = 60;
            dvgSorterenBreuken.Columns[0].ReadOnly = true;

            textBoxAantalSeconden.Enabled = false;
            random = new Random();

        }



        private void breukenDataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)//ok
        {

            if (e.ColumnIndex == 1 && !e.FormattedValue.ToString().Equals(""))
            {

                breukenDataGridView.Rows[e.RowIndex].ErrorText = "";
                Regex breukPattern = new Regex("^(-)?[0-9]*\\/{1}(-)?[1-9]{1}[0-9]*$"); // 20 minuten van mijn dag weg!
                if (breukPattern.IsMatch(e.FormattedValue.ToString()))
                {
                    string[] operanden = e.FormattedValue.ToString().Split('/');
                    breukContainer[e.RowIndex].Teller = int.Parse(operanden[0]);
                    breukContainer[e.RowIndex].Noemer = int.Parse(operanden[1]);
                }
                else
                {
                    breukenDataGridView.Rows[e.RowIndex].ErrorText = "Ongeldig formaat. Breuken moeten in de vorm 1/2 worden ingetypt.";
                    e.Cancel = true;
                }
            }
        }

        private void numericUpDown1_ValueChanged(object sender, EventArgs e)//ok
        {
            decimal waarde = ((NumericUpDown)sender).Value;
            decimal verschil = breukenLijst.Rows.Count - waarde;

            if (verschil < 0) //Aantal breuken in de lijst verhogen
            {
                for (int i = 1; i <= Math.Abs(verschil); i++)
                {
                    breukenLijst.Rows.Add(breukContainer.Breuken.Count + 1, "");
                    breukContainer.Add(new Breuk()); //voor elk element in de lijst een bijbehorende breuk hebben
                }
            }
            else
            {
                if (verschil > 0) //Aantal breuken in de lijst verlagen
                {
                    for (int i = breukenLijst.Rows.Count; i > waarde; i--)
                    {
                        breukenLijst.Rows[i - 1].Delete();
                        breukContainer.Breuken.RemoveAt(breukContainer.Breuken.Count - 1);
                    }
                }
            }
        }

        private void radioButton1_CheckedChanged(object sender, EventArgs e)//ok
        {
            if (((RadioButton)sender).Checked)
            {
                breukenDataGridView.Enabled = true;
                breukenDataGridView.GridColor = SystemColors.ControlText;
                maakBreukenButton.Enabled = false;
            }
            else
            {
                breukenDataGridView.Enabled = false;
                breukenDataGridView.GridColor = Color.HotPink;
                maakBreukenButton.Enabled = true;
            }
        }

        private void maakBreukenButton_Click(object sender, EventArgs e)//ok
        {
            if (zonderBeperkingen.Checked)
            {
                for (int i = 0; i < breukContainer.Breuken.Count; i++)
                {
                    breukContainer[i] = new Breuk(-80, 300, -80, 300);
                    ((DataRow)breukenLijst.Rows[i])[1] = breukContainer[i].Teller + "/" + breukContainer[i].Noemer;
                }
            }
            else
            {
                if (eenvoudigeBreuken.Checked == true)
                {
                    if (textBoxOndergrens.Text.Trim().Length > 0 || textBoxBovengrens.Text.Trim().Length > 0)
                    {
                        int num1, num2;
                        int.TryParse(textBoxOndergrens.Text.Trim(), out num1);
                        int.TryParse(textBoxBovengrens.Text.Trim(), out num2);

                        if (num1 <= num2)
                        {

                            for (int i = 0; i < breukContainer.Breuken.Count; i++)
                            {
                                breukContainer[i] = new Breuk(num1, num2, num1, num2);
                                ((DataRow)breukenLijst.Rows[i])[1] = breukContainer[i].Teller + "/" + breukContainer[i].Noemer;
                            }
                        }
                        else
                        {
                            MessageBox.Show("De ondergrens moet kleiner zijn dan de bovengrens.", "Ongeldige invoer",
                            MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                        }
                    }
                    else
                    {
                        MessageBox.Show("U moet een geldige boven- en ondergrens opgeven.", "Ongeldige invoer",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    }
                }
            }
        }

        private void numeriekeTextBox_Validating(object sender, CancelEventArgs e)//ok
        {
            double num;
            bool isNum = double.TryParse(((TextBox)sender).Text.Trim(), out num);

            if (!isNum)
            {
                MessageBox.Show("Gelieve enkel een numerieke waarde in te vullen.", "Ongeldige invoer",
                MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                e.Cancel = true;
            }

        }

        // De tekstvelden bij breuken met beperkingen
        private void radioButton3_CheckedChanged(object sender, EventArgs e)//ok
        {
            if (((RadioButton)sender).Checked)
            {
                textBoxOndergrens.Enabled = true;
                textBoxBovengrens.Enabled = true;
            }
            else
            {
                textBoxOndergrens.Enabled = false;
                textBoxBovengrens.Enabled = false;
            }
        }

        private void butMaakOpgaves_Click(object sender, EventArgs e)//ok
        {
            if (breukContainer.isGeldig())
            {
                dtSorterenBreuken.Clear();
                dtOpgaven.Clear();
                dgvOpgaven.Columns[2].Visible = false;
                int hoeveel = breukenLijst.Rows.Count;

                if (rdbBasisBewerkingen.Checked)
                {
                    basisOpgaveGenereren();
                }

                if (rdbRandombewerkingen.Checked)
                {
                    try
                    {
                        hoeveel = Int32.Parse(textBoxAantalOpgaves.Text);
                    }
                    catch (Exception)
                    {
                    }

                    //random opgaven maken
                    for (int i = 0; i < hoeveel; i++)
                    {
                        
                        randomOpgaveGenereren();
                    }
                }

                if (tijdsLimiet.Checked)
                {
                    //Timer activeren
                    dtOpgaven.Clear();
                    randomOpgaveGenereren();
                    try { hoeveel = Int32.Parse(textBoxAantalOpgaves.Text); }
                    catch (Exception) { hoeveel = 10; }
                    aantalbewerkingen = hoeveel - 1;
                    totaalbewerkingen = aantalbewerkingen;
                    int aantalSeconden = 10;
                    try
                    {
                        aantalSeconden = Int32.Parse(textBoxAantalSeconden.Text);
                    }
                    catch (Exception)
                    {
                    }
                    progressBar.Maximum = aantalSeconden;
                    timer1 = new Timer();
                    timer1.Interval = aantalSeconden * 1000;
                    timer1.Start();
                    timer1.Tick += new EventHandler(TimerTick);
                    timer2 = new Timer();
                    timer2.Interval = 1000;
                    progressBar.Value = 1;
                    timer2.Start();
                    timer2.Tick += new EventHandler(TimerTick2);
                }

                //dgvSorterenBreuken opmaken
                sorterenBreuken = new List<Breuk>();
                correctGesorteerdeBreuken = new List<Breuk>();
                foreach (Breuk b in breukContainer.Breuken)
                {
                    sorterenBreuken.Add(b);
                    correctGesorteerdeBreuken.Add(b);
                    DataRow row = dtSorterenBreuken.NewRow();
                    row[0] = b.ToString();
                    dtSorterenBreuken.Rows.Add(row);
                }
                correctGesorteerdeBreuken.Sort();
            }
            else
            {
                MessageBox.Show("U moet alle breuken van een correcte waarde voorzien", "Ongeldige invoer",
                MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        }

        private void TimerTick(object sender, EventArgs eArgs)//ok
        {
            if (aantalbewerkingen != 0)
            {
                progressBar.Value = 0;
                DataRow row = dtOpgaven.Rows[dtOpgaven.Rows.Count - 1];
                //Ervoor zorgen dat nadat de tijd om is er geen aanpassing meer kan gebeuren
                dgvOpgaven.Rows[totaalbewerkingen - aantalbewerkingen].ReadOnly = true;
                dgvOpgaven.Rows[totaalbewerkingen - aantalbewerkingen].Cells[1].Style.BackColor = Color.Orange;
                dgvOpgaven.Columns[0].ReadOnly = false;
                randomOpgaveGenereren();
                aantalbewerkingen--;
            }
            else
            {
                dgvOpgaven.Rows[totaalbewerkingen - aantalbewerkingen].ReadOnly = true;
                dgvOpgaven.Rows[totaalbewerkingen - aantalbewerkingen].Cells[1].Style.BackColor = Color.Orange;
                timer1.Stop();
                timer2.Stop();
            }
        }

        private void TimerTick2(object sender, EventArgs eArgs)//ok
        {
            progressBar.PerformStep();
        }

        private void randomOpgaveGenereren()//ok
        {
            dtOpgaven.Rows.Add(Bewerking());
        }

        private void basisOpgaveGenereren()//ok
        {
            for (int i = 0; i < breukenLijst.Rows.Count - 1; i = i + 2)
            {
                dtOpgaven.Rows.Add(Bewerking(" + ", Breuk.Optellen, breukContainer[i], breukContainer[i + 1]));

                dtOpgaven.Rows.Add(Bewerking(" - ", Breuk.Aftrekken, breukContainer[i], breukContainer[i + 1]));

                dtOpgaven.Rows.Add(Bewerking(" * ", Breuk.Vermenigvuldigen, breukContainer[i], breukContainer[i + 1]));

                dtOpgaven.Rows.Add(Bewerking(" : ", Breuk.Delen, breukContainer[i], breukContainer[i + 1]));
            }
        }
        private DataRow Bewerking()//ok
        {
            DataRow row = dtOpgaven.NewRow();
            String str = "";
            List<Breuk> breukjes= new List<Breuk>();
            List<DelegateBreukenBewerking> bewerkingen= new List<DelegateBreukenBewerking>();
            Breuk temp = breukContainer[random.Next(0, breukContainer.Count)];
            breukjes.Add(temp);
            str=str+temp.ToString();
            String[] volgorde = { "*", ":", "+", "-" };
            List<String> operanden= new List<String>();
            for (int i = 0; i < random.Next(1, 5); i++)
            {
                switch (random.Next(0, 4))
                {
                    case 0: 
                        bewerkingen.Add(Breuk.Optellen);
                        str = str + " + ";
                        operanden.Add("+");
                        break;
                    case 1: 
                        bewerkingen.Add(Breuk.Aftrekken);
                        str = str + " - ";
                        operanden.Add("-");
                        break;
                    case 2:
                        bewerkingen.Add(Breuk.Vermenigvuldigen);
                        str = str + " * ";
                        operanden.Add("*");
                        break;
                    case 3:
                        bewerkingen.Add(Breuk.Delen);
                        str = str + " : ";
                        operanden.Add(":");
                        break;
                }
                temp = breukContainer[random.Next(0, breukContainer.Count)];
                breukjes.Add(temp);
                str = str + temp.ToString();
            }
            row[0] = str;
            row[2] = Breuk.Vereenvoudig(breukContainer.doeBewerkingMetVolgorde(bewerkingen.ToArray(),breukjes.ToArray(),operanden.ToArray(),volgorde)).ToString();

            return row;

        }

        private DataRow Bewerking(String bewerking, DelegateBreukenBewerking d, Breuk b1, Breuk b2)//ok
        {
            DataRow row = dtOpgaven.NewRow();
            String str = b1.ToString() + bewerking + b2.ToString();
            row[0] = str;
            row[2] = Breuk.Vereenvoudig(d(b1, b2)).ToString();
            return row;
        }

        private DataRow Bewerking(String bewerking, DelegateBreukenBewerking d)//ok
        {
            int breuk1index = random.Next(0, (int)aantalBreukenUpDown.Value);
            int breuk2index = random.Next(0, (int)aantalBreukenUpDown.Value);
            return Bewerking(bewerking, d, breukContainer[breuk1index], breukContainer[breuk2index]);
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)//ok
        {
            textBoxAantalSeconden.Enabled = true;
        }

        private void butToonOplossingen_Click(object sender, EventArgs e)//ok
        {
            dgvOpgaven.Columns[2].Visible = true;
        }

        private void butEvalueerOpgaven_Click(object sender, EventArgs e)//ok
        {
            for (int i = 0; i < dtOpgaven.Rows.Count; i++)
            {
                DataRow row = dtOpgaven.Rows[i];
                if (!row[1].ToString().Equals(row[2].ToString()))
                {
                    dgvOpgaven.Rows[i].Cells[1].Style.BackColor = Color.Red;
                }
                else
                {
                    dgvOpgaven.Rows[i].Cells[1].Style.BackColor = Color.Green;
                }
            }

            //Controleren van sorteren van breuken
            for (int i = 0; i < dtSorterenBreuken.Rows.Count; i++)
            {
                if (!dtSorterenBreuken.Rows[i].ItemArray[0].ToString().Equals(correctGesorteerdeBreuken[i].ToString()))
                {
                    dvgSorterenBreuken.Rows[i].Cells[0].Style.BackColor = Color.Red;
                }
                else
                {
                    dvgSorterenBreuken.Rows[i].Cells[0].Style.BackColor = Color.Green;
                }
            }
        }

        private void butOmhoog_Click(object sender, EventArgs e)//ok
        {
            if (dvgSorterenBreuken.SelectedCells.Count > 0)
            {
                int index = dvgSorterenBreuken.SelectedCells[0].RowIndex;
                if (index >= 1)
                {
                    Breuk temp = sorterenBreuken[index];
                    sorterenBreuken[index] = sorterenBreuken[index - 1];
                    sorterenBreuken[index - 1] = temp;

                    dtSorterenBreuken.Clear();

                    foreach (Breuk b in sorterenBreuken)
                    {
                        dtSorterenBreuken.Rows.Add(b.ToString());
                    }
                }
            }
        }

        private void butOmlaag_Click(object sender, EventArgs e)//ok
        {
            if (dvgSorterenBreuken.SelectedCells.Count > 0)
            {
                int index = dvgSorterenBreuken.SelectedCells[0].RowIndex;
                if (index <= dvgSorterenBreuken.Rows.Count - 2)
                {
                    Breuk temp = sorterenBreuken[index];
                    sorterenBreuken[index] = sorterenBreuken[index + 1];
                    sorterenBreuken[index + 1] = temp;

                    dtSorterenBreuken.Clear();

                    foreach (Breuk b in sorterenBreuken)
                    {
                        dtSorterenBreuken.Rows.Add(b.ToString());
                    }
                }
            }

        }


    }

}
